<?php
namespace Common\Library\Rong;
/**
 * 融宝支付
 *
 * @since: 2016年12月30日 下午3:37:43
 * @author: xielu
 * @version: V1.0.0
 */
class RongpayService{
    //版本号
    static $version= "3.1.6";
    //请求处理地址
    static $apiUrl = "http://api.reapal.com";
    //字符编码格式，目前支持 utf-8
    static $charset = "utf-8";
    //签名方式，目前只支持MD5不需修改
	static $sign_type = "MD5";
	//访问模式,根据自己的服务器是否支持ssl访问，若支持请选择https；若不支持请选择http
    static $transport = "http";

	/**
	 * 支付表单
	 * @param $paramarr
	 * @param $reapalPublicKey
	 * @param $apiKey
	 * @param $url
	 * @return string
	 */
	public static function buildForm($paramarr, $reapalPublicKey, $apiKey){
		
		$gateway = self::$apiUrl.'/web/portal';//访问地址
		$paramarr = self::argSort($paramarr);
		$mySign = self::buildMysign($paramarr, $apiKey);//生成签名结果
		$paramarr['sign'] = $mySign;
		$generateAESKey = self::generateAESKey();
		$encryptkey = self::RSAEncryptkey($generateAESKey,$reapalPublicKey);
		$data = self::AESEncryptRequest($generateAESKey,$paramarr);
		//post方式传递
		$sHtml = "<form id=\"rongpaysubmit\" name=\"rongpaysubmit\" action=\"".$gateway."\" method=\"post\">"
		."<input type=\"hidden\" name=\"merchant_id\" value=\"".$paramarr['merchant_id']."\"/>"
		."<input type=\"hidden\" name=\"data\" value=\"".$data."\"/>"
		."<input type=\"hidden\" name=\"encryptkey\" value=\"".$encryptkey."\"/>"
		//submit按钮控件请不要含有name属性
		."<input type=\"submit\" class=\"button_p2p\" value=\"融宝支付确认付款\"></form>";

		return $sHtml;
	}

	public static function buildMysign($paramarr, $apiKey){
		$prestr = self::createLinkString($paramarr);
		return md5($prestr.$apiKey);
	}

	private static function createLinkString($array){
		$paramarr = self::paraFilter($array);
		$arg  = "";
		while (list ($apiKey, $val) = each ($paramarr))
		{
			$arg.=$apiKey."=".$val."&";
		}
		$arg = substr($arg,0,count($arg)-2);		     //去掉最后一个&字符
		return $arg;
	}


	/**
		*除去数组中的空值和签名参数
		*$parameter 签名参数组
		*return 去掉空值与签名参数后的新签名参数组
	 */
	private static function paraFilter($parameter)
	{
		$para = array();
		while (list ($key, $val) = each ($parameter))
		{
			if($key == "sign" || $key == "sign_type" || $val == "")
			{
				continue;
			}
			else
			{
				$para[$key] = $parameter[$key];
			}
		}
		return $para;
	}
	/********************************************************************************/

	/**对数组排序
		*$array 排序前的数组
		*return 排序后的数组
	 */
	public static function argSort($array)
	{
		ksort($array);
		reset($array);
		return $array;
	}
	//签名函数
	public static function createSign ($paramArr,$apiKey) {
		global $appSecret;
		$sign = $appSecret;
		ksort($paramArr);
		foreach ($paramArr as $key => $val) {
			if ($key != '' && $val != '') {
				$sign .= $key.'='.$val.'&';
			}
		}

		$sign = substr ( $sign,0,(strlen ( $sign )-1));
		$sign.=$appSecret;
		$sign = md5($sign.$apiKey);
		return $sign;
	}
	/**
	 * 生成一个随机的字符串作为AES密钥
	 *
	 * @param number $length
	 * @return string
	 */
	public static function generateAESKey($length=16){
		$baseString = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
		$AESKey = '';
		$_len = strlen($baseString);
		for($i=1;$i<=$length;$i++){
			$AESKey .= $baseString[rand(0, $_len-1)];
		}
		return $AESKey;
	}
	/**
	 * 通过RSA，使用融宝公钥，加密本次请求的AESKey
	 *
	 * @return string
	 */
	public static function RSAEncryptkey($encryptKey,$reapalPublicKey){
		$public_key= self::getPublicKey($reapalPublicKey);
		$pu_key = openssl_pkey_get_public($public_key);//这个函数可用来判断公钥是否是可用的

		openssl_public_encrypt($encryptKey,$encrypted,$pu_key);//公钥加密

		return base64_encode($encrypted);



	}
	/**
	 * 通过RSA，使用融宝公钥，加密本次请求的AESKey
	 *
	 * @return string
	 */
	public static function RSADecryptkey($encryptKey,$merchantPrivateKey){
		$private_key= self::getPrivateKey($merchantPrivateKey);

		$pi_key =  openssl_pkey_get_private($private_key);//这个函数可用来判断私钥是否是可用的，可用返回资源id Resource id

		openssl_private_decrypt(base64_decode($encryptKey),$decrypted,$pi_key);//私钥解密
		return $decrypted;


	}
	/**
	 * 通过AES加密请求数据
	 *
	 * @param array $query
	 * @return string
	 */
	public static function AESEncryptRequest($encryptKey,array $query){

		return self::encrypt(json_encode($query),$encryptKey);

	}
	/**
	 * 通过AES解密请求数据
	 *
	 * @param array $query
	 * @return string
	 */
	public static function AESDecryptResponse($encryptKey,$data){
		return self::decrypt($data,$encryptKey);

	}
	public static function encrypt($input, $key) {
		$size = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB);
		$input = self::pkcs5_pad($input, $size);
		$td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_ECB, '');
		$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
		mcrypt_generic_init($td, $key, $iv);
		$data = mcrypt_generic($td, $input);
		mcrypt_generic_deinit($td);
		mcrypt_module_close($td);
		$data = base64_encode($data);
		return $data;
	}

	public static function pkcs5_pad ($text, $blocksize) {
		$pad = $blocksize - (strlen($text) % $blocksize);
		return $text . str_repeat(chr($pad), $pad);
	}
	public static function decrypt($sStr, $sKey) {
		$decrypted= mcrypt_decrypt(
			MCRYPT_RIJNDAEL_128,
			$sKey,
			base64_decode($sStr),
			MCRYPT_MODE_ECB
		);

		$dec_s = strlen($decrypted);
		$padding = ord($decrypted[$dec_s-1]);
		$decrypted = substr($decrypted, 0, -$padding);
		return $decrypted;
	}

	public static function getPrivateKey($cert_path) {
		$pkcs12 = file_get_contents ( $cert_path );

		return $pkcs12;
	}
	public static function getPublicKey($cert_path) {
		$pkcs12 = file_get_contents ( $cert_path );
		return $pkcs12;
	}
	public static function sendHttpRequest($params, $url) {
		$opts = self::getRequestParamString ( $params );
		$ch = curl_init ();
		curl_setopt ( $ch, CURLOPT_URL, $url );
		curl_setopt ( $ch, CURLOPT_POST, 1 );
		curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, false);//不验证证书
		curl_setopt ( $ch, CURLOPT_SSL_VERIFYHOST, false);//不验证HOST
		curl_setopt ( $ch, CURLOPT_SSLVERSION, 3);
		curl_setopt ( $ch, CURLOPT_HTTPHEADER, array (
			'Content-type:application/x-www-form-urlencoded;charset=UTF-8'
		) );
		curl_setopt ( $ch, CURLOPT_POSTFIELDS, $opts );

		/**
		 * 设置cURL 参数，要求结果保存到字符串中还是输出到屏幕上。
		 */
		curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, true );

		// 运行cURL，请求网页
		$html = curl_exec ( $ch );
		// close cURL resource, and free up system resources
		curl_close ( $ch );
		return $html;
	}

	/**
	 * 组装报文
	 *
	 * @param unknown_type $params
	 * @return string
	 */
	public static function getRequestParamString($params) {
		$params_str = '';
		foreach ( $params as $key => $value ) {
			$params_str .= ($key . '=' . (!isset ( $value ) ? '' : urlencode( $value )) . '&');
		}
		return substr ( $params_str, 0, strlen ( $params_str ) - 1 );
	}


	public static function send($paramArr, $url, $apiKey, $reapalPublicKey, $merchant_id){
		//生成签名
		$sign = self::createSign($paramArr,$apiKey);

		$paramArr['sign'] = $sign;
		$paramArr['sign_type'] = 'MD5';
		//生成AESkey
		$generateAESKey = self::generateAESKey();
		$request = array();
		$request['merchant_id'] = $merchant_id;
		//加密key
		$request['encryptkey'] = self::RSAEncryptkey($generateAESKey,$reapalPublicKey);
		//加密数据
		$request['data'] = self::AESEncryptRequest($generateAESKey,$paramArr);
		return self::sendHttpRequest($request,$url);
	}
}
?>